  #include "stdinc.h"
#include "App.h"
#include "Listener.h"
#include "Graphics/CopyRenderer.h"
#include "Graphics/MapRenderer.h"
#include "Graphics/Creatures.h"
#include "DwarfFort/Interface.h"
#include "GUI/DwarfGUI.h"



 



using namespace Main;

class App * Ogre::Singleton<class App>::ms_Singleton;


App::App(void) 
	:Loggable("Main::App"),
	 mLogFile("OgreDwarf.log")
{
	mRoot = 0;
	mFrameListener = 0;
	mGUI = 0;
	mDwarfFortInterface = new DwarfFort::Interface();
	mLogger.registerListener(&mLogFile);
	logMessage("App created");

}


App::~App(void)
{
 
//	Lugre::cShell& shell = Lugre::cShell::GetSingleton();
//	shell.DeInit();

	destroyScene();
    if (mFrameListener)
        delete mFrameListener;
    if (mGUI)
		delete mGUI;
	
	
	if (mRoot)
        delete mRoot;
	
}


int App::Render(void)
{
	if (!mWindow->isPrimary()) _asm int 3;
	if (mWindow->isActive())
		return mRoot->renderOneFrame();
	return 1;
}

void App::MainLoop(void)
{
	bool still_running = true;
	logMessage("Entering mainLoop");
	while (still_running)
	{
	//	_asm int 3;
		mDwarfFortInterface->updateTimer();
		if (mDwarfFortInterface->checkGameTimer()) 
			still_running = DwarfFort::Interface::getSingleton().DwarfFortGameLoop(); 
		if (!still_running) 
			logMessage("Game Loop returned false, exiting");
		Ogre::WindowEventUtilities::messagePump(); 
		if (still_running && mWindow->isActive() /*&& 
			mDwarfFortInterface->checkRenderTimer()*/)
		{
			
			still_running = mRoot->renderOneFrame();
		}
		if (!still_running) 
			logMessage("Render Loop returned false, exiting");
	}
	logMessage("Exiting mainLoop");
//	mRoot->startRendering();
}

    
bool App::Setup(void)
{
#ifdef _DEBUG
	Ogre::String plugStr = "plugins_d.cfg";
#else
	Ogre::String plugStr = "plugins.cfg";
#endif
        mRoot = new Root(plugStr);
		mDwarfFortInterface->connectToDwarfFort();
		mDwarfFortInterface->PatchGame();
		bool carryOn = mDwarfFortInterface->DwarfFortSetup();

		if (!carryOn) return false;
		
        setupResources();
        carryOn = configure();
        if (!carryOn) return false;

        chooseSceneManager();

		


        createCamera();
        createViewports();

        // Set default mipmap level (NB some APIs ignore this)
        TextureManager::getSingleton().setDefaultNumMipmaps(5);

		// Create any resource listeners (for loading screens)
		createResourceListener();
		// Load resources
		loadResources();

		// Create the scene
        createScene();
		mGUI = new GUI::DwarfGUI(mWindow);
        createFrameListener();

		
	//	createGUI();
        return true;

    }
    /** Configures the application - returns false if the user chooses to abandon configuration. */
bool App::configure(void)
    {
	try
	{
			mRoot->showConfigDialog();
			mRoot->restoreConfig();
		    mWindow = mRoot->initialise(true);
	}
	catch( Ogre::InvalidStateException e)
	{
		std::string desc = e.getFullDescription(); 
	}
	
	return true;
        
    }

void App::chooseSceneManager(void)
{
    // Create the SceneManager, in this case a generic one
	
    mSceneMgr = mRoot->createSceneManager("OctreeSceneManager", "ExampleSMInstance");
	mDFScene = mRoot->createSceneManager(ST_GENERIC,"DFScene");
}
void App::createCamera(void)
{
    // Create the camera
    mCamera = mSceneMgr->createCamera("PlayerCam");

    // Position it at 500 in Z direction
    
	mCamera->setPosition(Vector3(100,70,100));
        // Look back along -Z
    mCamera->lookAt(Vector3(0,0,0));
    mCamera->setNearClipDistance( 1 );
    mCamera->setFarClipDistance( 1000 );
    // Look back along -Z

}
void App::createFrameListener(void)
{
    mFrameListener= new Listener(mWindow, mCamera,mGUI,mMapRenderer, true,true);
    mFrameListener->showDebugOverlay(true);
    mRoot->addFrameListener(mFrameListener);
}

void App::createScene(void) 
{
        mSceneMgr->setAmbientLight(ColourValue(0.5, 0.5, 0.5));

        // Create a light
        Light* l = mSceneMgr->createLight("MainLight");
        // Accept default settings: point light, white diffuse, just set position
        // NB I could attach the light to a SceneNode if I wanted it to move automatically with
        //  other objects, but I don't
        l->setPosition(20,80,50);

        // Fog
        // NB it's VERY important to set this before calling setWorldGeometry 
        // because the vertex program picked will be different
        ColourValue fadeColour(0.93, 0.86, 0.76);
       // mSceneMgr->setFog( FOG_LINEAR, fadeColour, .001, 500, 1000);
        mWindow->getViewport(0)->setBackgroundColour(fadeColour);

 //       std::string terrain_cfg("terrain.cfg");
   //     mSceneMgr -> setWorldGeometry( terrain_cfg );

		
		
		 

		
		// Infinite far plane?
		
	/*	if (mRoot->getRenderSystem()->getCapabilities()->hasCapability(RSC_INFINITE_FAR_PLANE))
        {
            mCamera->setFarClipDistance(0);
        }*/
		
		
		this->mCopyListener = new Graphics::CopyRenderer(mWindow);
		mCopyListener->prepRenderBuffer();
		mDFScene->addRenderQueueListener(mCopyListener);/**/

		this->mCreatureManager = new Graphics::CreatureManager(mSceneMgr);

		this->mMapRenderer = new Graphics::MapRenderer(mSceneMgr,this->mCamera);
		
		

}//

void App::destroyScene(void)
{
	mCopyListener->destroyRenderBuffer(); 
	delete mCopyListener;
	mCopyListener = NULL;

	
	delete mMapRenderer;

}    // Optional to override this

void App:: createViewports(void)
{
    // Create one viewport, entire window
    Viewport* vp = mWindow->addViewport(mCamera);
    vp->setBackgroundColour(ColourValue(0,0,0));
	vp->setOverlaysEnabled(true);
    // Alter the camera aspect ratio to match the viewport
    mCamera->setAspectRatio(
        Real(vp->getActualWidth()) / Real(vp->getActualHeight()));
}

/// Method which will define the source of resources (other than current folder)
void App::setupResources(void)
    {
        // Load resource paths from config file
        ConfigFile cf;
        cf.load("resources.cfg");

        // Go through all sections & settings in the file
        ConfigFile::SectionIterator seci = cf.getSectionIterator();

        String secName, typeName, archName;
        while (seci.hasMoreElements())
        {
            secName = seci.peekNextKey();
            ConfigFile::SettingsMultiMap *settings = seci.getNext();
            ConfigFile::SettingsMultiMap::iterator i;
            for (i = settings->begin(); i != settings->end(); ++i)
            {
                typeName = i->first;
                archName = i->second;
                ResourceGroupManager::getSingleton().addResourceLocation(
                    archName, typeName, secName);
            }
        }
    }

	/// Optional override method where you can create resource listeners (e.g. for loading screens)
	void App::createResourceListener(void)
	{

	}

	/// Optional override method where you can perform resource group loading
	/// Must at least do ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
	void App::loadResources(void)
	{
		// Initialise, parse scripts etc
		ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
		const Ogre::String& defGrp =  Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME;
		Ogre::TexturePtr p = mRoot->getTextureManager()->load(Ogre::String("DwarfCurses.png"),defGrp);

		MeshManager::getSingleton().load("Box.mesh",defGrp);
	}




	